{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Generative Adversarial Networks\n",
    "\n",
    "This notebook implements a very basic GAN with MLPs for the 2 networks."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "\n",
    "import tensorflow as tf\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from tensorflow.examples.tutorials.mnist import input_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Extracting MNIST_data/train-images-idx3-ubyte.gz\n",
      "Extracting MNIST_data/train-labels-idx1-ubyte.gz\n",
      "Extracting MNIST_data/t10k-images-idx3-ubyte.gz\n",
      "Extracting MNIST_data/t10k-labels-idx1-ubyte.gz\n"
     ]
    }
   ],
   "source": [
    "mnist = input_data.read_data_sets(\"MNIST_data/\")\n",
    "images = mnist.train.images"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Weight initialisation\n",
    "\n",
    "The weights will be initiliased using the Xavier initialisation method [1]. In this case, this is just a Gaussian distribution with a custom standard deviation: the standard deviation is inversely proportional to the number of neurons feeding into the neuron.\n",
    "\n",
    "$$ \\mathbf{w}_i \\sim \\mathcal{N}(0, \\frac{1}{n_{i-1}}) $$\n",
    "\n",
    "where $n_{i-1}$ is the number of inputs that feed into the current neuron.\n",
    "\n",
    "I also tried with regular Gaussian (i.e. constant $\\sigma$) and with uniform distribution, but I did not manage to get the network learning.\n",
    "\n",
    "[1] *Glorot, Xavier, and Yoshua Bengio. \"Understanding the difficulty of training deep feedforward neural networks.\" Aistats. Vol. 9. 2010.*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def xavier_initializer(shape):\n",
    "    return tf.random_normal(shape=shape, stddev=1/shape[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Architecture"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Generator\n",
    "z_size = 100 # Latent vector dimension\n",
    "g_w1_size = 400 \n",
    "g_out_size = 28 * 28\n",
    "\n",
    "# Discriminator\n",
    "x_size = 28 * 28\n",
    "d_w1_size = 400\n",
    "d_out_size = 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "z = tf.placeholder('float', shape=(None, z_size))\n",
    "X = tf.placeholder('float', shape=(None, x_size))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Weights"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "g_weights = {\n",
    "    'w1': tf.Variable(xavier_initializer(shape=(z_size, g_w1_size))),\n",
    "    'b1': tf.Variable(tf.zeros(shape=[g_w1_size])),\n",
    "    'out': tf.Variable(xavier_initializer(shape=(g_w1_size, g_out_size))),\n",
    "    'b2': tf.Variable(tf.zeros(shape=[g_out_size])),\n",
    "}\n",
    "\n",
    "d_weights ={\n",
    "    'w1': tf.Variable(xavier_initializer(shape=(x_size, d_w1_size))),\n",
    "    'b1': tf.Variable(tf.zeros(shape=[d_w1_size])),\n",
    "    'out': tf.Variable(xavier_initializer(shape=(d_w1_size, d_out_size))),\n",
    "    'b2': tf.Variable(tf.zeros(shape=[d_out_size])),\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Models\n",
    "\n",
    "The models were chosen to be very simple, so just an MLP with 1 hidden layer and 1 output layer."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "def G(z, w=g_weights):\n",
    "    h1 = tf.nn.relu(tf.matmul(z, w['w1']) + w['b1'])\n",
    "    return tf.sigmoid(tf.matmul(h1, w['out']) + w['b2'])\n",
    "\n",
    "def D(x, w=d_weights):\n",
    "    h1 = tf.nn.relu(tf.matmul(x, w['w1']) + w['b1'])\n",
    "    return tf.sigmoid(tf.matmul(h1, w['out']) + w['b2'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Latent distribution\n",
    "\n",
    "This function generates a prior for G."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def generate_z(n=1):\n",
    "    return np.random.normal(size=(n, z_size))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "sample = G(z) # To be called during session"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cost\n",
    "\n",
    "The cost functions are the ones used in the original GAN paper [2], using the suggestion of switching the loss for G from minimising $\\frac{1}{m}\\sum_{i=1}^m(1-D(G(\\mathbf{z}))$ to maximising $\\frac{1}{m}\\sum_{i=1}^m(D(G(\\mathbf{z}))$.\n",
    "\n",
    "Note that because both need to be maximised, and TF is designed to minimise, we take the negative values below.\n",
    "\n",
    "\n",
    "[2] *Goodfellow, Ian, et al. \"Generative adversarial nets.\" Advances in neural information processing systems. 2014.*\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "G_objective = -tf.reduce_mean(tf.log(D(G(z))))\n",
    "D_objective = -tf.reduce_mean(tf.log(D(X)) + tf.log(1 - D(G(z))))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Optimisation\n",
    "\n",
    "Note that each of the optimiser takes a `var_list` argument to only consider the variables provided. This is because we don't want D to train G when D is trained, but rather freeze the weights from G and only concern about D (and the same for G)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "G_opt = tf.train.AdamOptimizer().minimize(\n",
    "    G_objective, var_list=g_weights.values())\n",
    "D_opt = tf.train.AdamOptimizer().minimize(\n",
    "    D_objective, var_list=d_weights.values())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Training"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAWEAAAFfCAYAAACfj30KAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAAPYQAAD2EBqD+naQAAIABJREFUeJztnXuMLNtV3r893fM4Z849XMWOH8FB2BgHLITlXAKxwODI\nSA6OZEAgiEEBgyKF8BBCCliWSGxwEguQLYeHIyLeCiDxCAIk40sg2MSAcTCBYBNsQWwMmHvxA91z\n7pmZ7p6enT96Vt/VX6+1965+nJrH+qRSVe2urq5H169WfXvtXSnnjFAoFAr1o52+NyAUCoWuswLC\noVAo1KMCwqFQKNSjAsKhUCjUowLCoVAo1KMCwqFQKNSjAsKhUCjUowLCoVAo1KMCwqFQKNSjhn1v\nQErpSQBeAuADAE763ZpQKBTaiA4AfCKAh3POHy0tuDUIp5S+AcC/AfA0AH8I4Jtyzv/LWPQlAH5y\nW9sRCoVCPeorAfxUaYGt2BEppS8H8HoArwbwfMwg/HBK6cnG4h/YxjaEQqHQBdAHagtsyxP+FgA/\nmHP+iZzznwD4OgBHAL7WWDYsiFAodFVV5dvGIZxS2gXwEIBfl7I866rt1wC8YNO/FwqFQpdZ24iE\nnwxgAOBRKn8UM384FAqFQue6nylqCUB0XhwKhUJK24DwRwBMATyVyp+C5eg4FAqFrrU2DuGc8wTA\nuwC8WMpSSul8/rc3/XuhUCh0mbWtPOE3APjxlNK7ALwTs2yJmwB+bEu/FwqFQpdSW4FwzvlnznOC\nvxMzW+IPALwk5/zhbfxeKBQKXValvl/0mVL6h5jZF6FQKHTV9FDO+fdLC0QHPqFQKNSjAsKhUCjU\nowLCoVAo1KMCwqFQKNSjAsKhUCjUowLCoVAo1KMCwqFQKNSjAsKhUCjUowLCoVAo1KMCwqFQKNSj\nAsKhUCjUowLCoVAo1KMCwqFQKNSjAsKhUCjUowLCoVAo1KMCwqFQKNSjAsKhUCjUowLCoVAo1KMC\nwqFQKNSjAsKhUCjUowLCoVAo1KMCwqFQKNSjAsKhUCjUowLCoVAo1KMCwqFQKNSjAsKhUCjUowLC\noVAo1KMCwqFQKNSjAsKhUCjUowLCoVAo1KOGfW9AKBTqXyml4uc55/u0JddPAeFQ6BqrBl9ruQDy\nZhUQDoWuqVoBXPpeAHl9BYRDoWsoC8BWWQ2y8p2A8eqKirlQKORGxSml+bDK90N1BYRDoWsmBqae\n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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f568f1aff28>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Hyper-parameters\n",
    "epochs = 50000\n",
    "batch_size = 128\n",
    "\n",
    "# Session\n",
    "with tf.Session() as sess:\n",
    "    sess.run(tf.global_variables_initializer())\n",
    "    \n",
    "    for _ in range(epochs):\n",
    "        sess.run(G_opt, feed_dict={\n",
    "            z: generate_z(batch_size)            \n",
    "        })\n",
    "        sess.run(D_opt, feed_dict={\n",
    "            X: images[np.random.choice(range(len(images)), batch_size)].reshape(batch_size, x_size),\n",
    "            z: generate_z(batch_size),\n",
    "        })\n",
    "\n",
    "    # Show a random image\n",
    "    image = sess.run(sample, feed_dict={z:generate_z()})\n",
    "    plt.imshow(image.reshape(28, 28), cmap='gray')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
